package com.papper.mng.exception;

import com.papper.common.enums.ResultEnum;
import com.papper.common.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author:LaJiao
 * @date 2022年03月24日
 * @time 13时27
 * @Description:
 */
@ControllerAdvice
public class GlobalExceptionHandler {
	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

	/**
	 * 处理自定义的业务异常
	 *
	 * @param req
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = ServiceException.class)
	public ModelAndView bizExceptionHandler(HttpServletRequest req, ServiceException e, HandlerMethod handler) {
		logger.error("发生业务异常！原因是:[{}]-[{}]", e.getCode(), e.getError());
		if (isReturnJson(handler)) {
			ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
			modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		} else {
			ModelAndView modelAndView = new ModelAndView("/error/error");
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		}
	}

	/**
	 * 数据校验异常
	 *
	 * @param req
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = IllegalArgumentException.class)
	public ModelAndView IllegalArgumentException(HttpServletRequest req, IllegalArgumentException e, HandlerMethod handler) {
		logger.error("数据校验异常！原因是:[{}]", e.getMessage());
		if (isReturnJson(handler)) {
			ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
			modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		} else {
			ModelAndView modelAndView = new ModelAndView("/error/error");
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		}
	}

	/**
	 * 处理空指针的异常
	 *
	 * @param req
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = NullPointerException.class)
	public ModelAndView exceptionHandler(HttpServletRequest req, NullPointerException e, HandlerMethod handler) {
		logger.error("发生空指针异常！原因是:[{}]", e);
		if (isReturnJson(handler)) {
			ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
			modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		} else {
			ModelAndView modelAndView = new ModelAndView("/error/error");
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		}
	}

	/**
	 * 处理其他异常
	 *
	 * @param req
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value = Exception.class)
	public ModelAndView exceptionHandler(HttpServletRequest req, Exception e, HandlerMethod handler) {
		logger.error("发生异常！原因是:[{}]", e);
		if (isReturnJson(handler)) {
			ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
			modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		} else {
			ModelAndView modelAndView = new ModelAndView("/error/error");
			modelAndView.addObject("message", e.getMessage());
			return modelAndView;
		}
	}

	private boolean isReturnJson(HandlerMethod handler) {
		if (handler.getBeanType().isAnnotationPresent(RestController.class)) {
			return true;
		}
		Method method = handler.getMethod();
		if (method.isAnnotationPresent(ResponseBody.class)) {
			return true;
		}
		return false;
	}
}
